#include "dvbinner.h"
#include "sipsiparser.h"
#include "builderplugin.h"
#include "dvbfun4plugin.h"

#define BUILDER_ACQUAINT_SECTION_RECV_MAX	20

typedef enum
{
	BUILDER_ACQUAINT_STATUS_IDLE,
	BUILDER_ACQUAINT_STATUS_WAIT_LOCK,
	BUILDER_ACQUAINT_STATUS_DATA_RECEIVING,
}BUILDER_ACQUAINT_STATUS_T;

typedef struct
{
	BUILDER_ACQUAINT_STATUS_T m_eStatus;
	builder_tuner_t* 	m_pstTunerList;
	unsigned int 		m_u32Num;
	unsigned int		m_u32CurIndex;
	unsigned int		m_u32FilterID;
	unsigned int		m_u32TimeOut;
	unsigned int		m_u32SectionRecvCnt;
	unsigned int		m_u32OperatorFound;
	unsigned char		m_au8SecRecvBitmap[256];//most 256 sections
	builder_section_t*	m_pstNitSections;
}builder_acquaint_control_t;

builder_acquaint_control_t stBuilderAcquaintManger = {BUILDER_ACQUAINT_STATUS_IDLE, NULL, 0, 0, BUILDER_INVALID_FILTER, 0, 0, 0};

static int BuilderAcquaintRecvNit()
{
	int s32Ret = -1;
	unsigned char au8Data[16];
	unsigned char au8Mask[16];

	mwDebug("PluginRecvNit() - entry\r\n");
	memset(au8Data, 0, sizeof(au8Data));
	memset(au8Mask, 0, sizeof(au8Mask));
	au8Data[0] = SIPSI_TID_NIT_ACTUAL;
	au8Mask[0] = 0xFF;
	s32Ret = DvbBuilderSetFilter(&stBuilderAcquaintManger.m_u32FilterID, SIPSI_PID_NIT, au8Data, au8Mask, 1);
	if(s32Ret == 0)
	{
		mwDebug("BuilderAcquaintRecvNit() - set filter OK\r\n");
	}
	else
	{
		mwDebug("BuilderAcquaintRecvNit() - set filter error\r\n");
	}
	mwDebug("BuilderAcquaintRecvNit() - return, s32Ret = %d\r\n", s32Ret);
	
	return s32Ret;
}

int BuilderAcquaintStart(builder_tuner_t* pstTunerList, unsigned int u32Num)
{
	int s32Ret = -1;

	mwDebug("BuilderAcquaintStart() - entry, pstTunerList = %p, u32Num = %d\r\n", pstTunerList, u32Num);
	if(pstTunerList && u32Num>0)
	{
		if(stBuilderAcquaintManger.m_eStatus == BUILDER_ACQUAINT_STATUS_IDLE)
		{
			stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_WAIT_LOCK;
			stBuilderAcquaintManger.m_pstTunerList = pstTunerList;
			stBuilderAcquaintManger.m_u32CurIndex = 0;
			stBuilderAcquaintManger.m_u32FilterID = 0;
			stBuilderAcquaintManger.m_u32Num = u32Num;
			stBuilderAcquaintManger.m_u32TimeOut = 10;
			stBuilderAcquaintManger.m_u32OperatorFound = 0;
			stBuilderAcquaintManger.m_pstNitSections = NULL;
			memset(stBuilderAcquaintManger.m_au8SecRecvBitmap, 0, sizeof(stBuilderAcquaintManger.m_au8SecRecvBitmap));
			s32Ret = DvbBuilderTunerLock(&stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex]);
		}
		else
		{
			mwError("BuilderAcquaintStart() - found status error, stBuilderAcquaintManger.m_eStatus = %d\r\n", stBuilderAcquaintManger.m_eStatus);
		}
	}
	else
	{
		mwError("BuilderAcquaintStart() - receive error param\r\n");
	}
	mwDebug("BuilderAcquaintStart() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int BuilderAcquaintStop()
{
	int s32Ret = -1;

	mwDebug("BuilderAcquaintStop() - entry\r\n");
	if(stBuilderAcquaintManger.m_eStatus == BUILDER_ACQUAINT_STATUS_DATA_RECEIVING)
	{
		DvbBuilderReleaseFilter(stBuilderAcquaintManger.m_u32FilterID);
		stBuilderAcquaintManger.m_u32FilterID = BUILDER_INVALID_FILTER;
	}
	stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_IDLE;
	if(stBuilderAcquaintManger.m_pstTunerList)
	{
		mwOsFreeMemory(stBuilderAcquaintManger.m_pstTunerList);
		stBuilderAcquaintManger.m_pstTunerList = NULL;
	}
	mwDebug("BuilderAcquaintStop() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int BuilderAcquaintLockFinish(builder_tuner_t* pstTunerInfo, unsigned int u32Lock)
{
	int s32Ret = -1;

	mwDebug("BuilderAcquaintLockFinish() - entry, pstTunerInfo = %p, u32Lock = %d\r\n", pstTunerInfo, u32Lock);
	if(stBuilderAcquaintManger.m_eStatus==BUILDER_ACQUAINT_STATUS_WAIT_LOCK)
	{
		if(pstTunerInfo->m_u32Freq == stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex].m_u32Freq)
		{
			if(u32Lock == 1)
			{
				s32Ret = BuilderAcquaintRecvNit();
				stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_DATA_RECEIVING;
				stBuilderAcquaintManger.m_u32TimeOut = 10;
				stBuilderAcquaintManger.m_u32SectionRecvCnt = 0;
				stBuilderAcquaintManger.m_pstNitSections = NULL;
				memset(stBuilderAcquaintManger.m_au8SecRecvBitmap, 0, sizeof(stBuilderAcquaintManger.m_au8SecRecvBitmap));
			}
			else
			{
				mwDebug("BuilderAcquaintLockFinish() - found freq unlock\r\n,  pstTunerInfo->m_u32Freq = %d\r\n", pstTunerInfo->m_u32Freq);
				stBuilderAcquaintManger.m_u32CurIndex++;
				if(stBuilderAcquaintManger.m_u32CurIndex < stBuilderAcquaintManger.m_u32Num)
				{
					stBuilderAcquaintManger.m_u32TimeOut = 10;
					s32Ret = DvbBuilderTunerLock(&stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex]);
					stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_WAIT_LOCK;
				}
			}
		}
	}
	mwDebug("BuilderAcquaintLockFinish() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int BuilderAcquaintDataRecv(unsigned int hFilter, unsigned char* pu8Data, unsigned int u32Len)
{
	int s32Ret = -1;
	builder_section_t* pstSection;
	builder_section_t* pstTmpSection;
	builder_section_t* pstTmpPrevSection;
	unsigned char u8SectionNum;
	unsigned char u8LastSectionNum;
	unsigned int i;

	mwDebug("BuilderAcquaintDataRecv() - entry, hFilter = 0x%x, pu8Data = %p, u32Len = %d\r\n", hFilter, pu8Data, u32Len);
	if(stBuilderAcquaintManger.m_eStatus == BUILDER_ACQUAINT_STATUS_DATA_RECEIVING)
	{
		s32Ret = 0;
		if(hFilter == stBuilderAcquaintManger.m_u32FilterID)
		{
			stBuilderAcquaintManger.m_u32SectionRecvCnt++;
			u8SectionNum = SiPsiGetSectionNo(pu8Data);
			u8LastSectionNum = SiPsiGetLastSectionNo(pu8Data);
			if(stBuilderAcquaintManger.m_au8SecRecvBitmap[u8SectionNum] == 0)
			{
				u32Len = SiPsiGetSectionLength(pu8Data) + 3;
				pstSection = DvbBuilderMemAlloc(sizeof(builder_section_t) + u32Len);
				if(pstSection)
				{
					memcpy(pstSection->m_au8Section, pu8Data, u32Len);
					pstTmpPrevSection = stBuilderAcquaintManger.m_pstNitSections;
					if(pstTmpPrevSection && SiPsiGetSectionNo(pstTmpPrevSection->m_au8Section)<u8SectionNum)
					{
						pstTmpSection = pstTmpPrevSection->m_pstNext;
						while(pstTmpSection)
						{
							if(SiPsiGetSectionNo(pstTmpSection->m_au8Section)>u8SectionNum)
								break;
							pstTmpPrevSection = pstTmpSection;
							pstTmpSection = pstTmpPrevSection->m_pstNext;
						}
						pstSection->m_pstNext = pstTmpSection;
						pstTmpPrevSection->m_pstNext = pstSection;
					}
					else
					{
						pstSection->m_pstNext = stBuilderAcquaintManger.m_pstNitSections;
						stBuilderAcquaintManger.m_pstNitSections = pstSection;
					}
				}
				else
				{	
					mwError("BuilderAcquaintDataRecv() -malloc section failed\r\n");
				}
				stBuilderAcquaintManger.m_au8SecRecvBitmap[u8SectionNum] = 1;
			}

			for(i=0; i<=u8LastSectionNum; i++)
			{
				if(stBuilderAcquaintManger.m_au8SecRecvBitmap[i] != 1)
				{
					break;
				}
			}

			if(i > u8LastSectionNum)
			{
				DvbBuilderReleaseFilter(stBuilderAcquaintManger.m_u32FilterID);
				stBuilderAcquaintManger.m_u32FilterID = BUILDER_INVALID_FILTER;
				stBuilderAcquaintManger.m_u32OperatorFound = 1;
			}
			else if(stBuilderAcquaintManger.m_u32SectionRecvCnt > BUILDER_ACQUAINT_SECTION_RECV_MAX)
			{
				DvbBuilderReleaseFilter(stBuilderAcquaintManger.m_u32FilterID);
				stBuilderAcquaintManger.m_u32FilterID = BUILDER_INVALID_FILTER;
				pstTmpSection = stBuilderAcquaintManger.m_pstNitSections;
				do
				{
					pstSection = pstTmpSection;
					pstTmpSection = pstSection->m_pstNext;
					DvbBuilderMemFree(pstSection);
				}while(pstTmpSection);
				stBuilderAcquaintManger.m_pstNitSections = NULL;
				
				stBuilderAcquaintManger.m_u32CurIndex++;
				if(stBuilderAcquaintManger.m_u32CurIndex < stBuilderAcquaintManger.m_u32Num)
				{
					stBuilderAcquaintManger.m_u32TimeOut = 10;
					s32Ret = DvbBuilderTunerLock(&stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex]);
					stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_WAIT_LOCK;
				}
			}

		}
		else
		{
			mwError("BuilderAcquaintDataRecv() - receive data handle no request, hFilter = 0x%x, stBuilderAcquaintManger.m_u32FilterID = 0x%x\r\n", hFilter, stBuilderAcquaintManger.m_u32FilterID);
		}
	}
	mwDebug("BuilderAcquaintDataRecv() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int BuilderAcquaintGetProcess(unsigned int* pu32DataOk, unsigned int* pu32Process)
{
	int s32Ret = -1;

	mwDebug("BuilderAcquaintGetProcess() - entry, pu32DataOk = %p, pu32Process = %p\r\n", pu32DataOk, pu32Process);
	s32Ret = 0;
	if(stBuilderAcquaintManger.m_eStatus != BUILDER_ACQUAINT_STATUS_IDLE)
	{
		if(stBuilderAcquaintManger.m_u32OperatorFound == 0)
		{
			*pu32Process = stBuilderAcquaintManger.m_u32CurIndex*100/(stBuilderAcquaintManger.m_u32Num);
			*pu32DataOk = 0;
		}
		else
		{
			*pu32Process = 100;
			*pu32DataOk = 1;
		}

		if(*pu32Process == 100)
		{
			stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_IDLE;
			if(stBuilderAcquaintManger.m_pstTunerList)
			{
				mwOsFreeMemory(stBuilderAcquaintManger.m_pstTunerList);
				stBuilderAcquaintManger.m_pstTunerList = NULL;
			}
		}
	}
	else
	{
		*pu32Process = 100;
		*pu32DataOk = 1;
	}
	mwDebug("BuilderAcquaintGetProcess() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int BuilderAcquaintTick()
{
	int s32Ret = -1;

	mwDebug("BuilderAcquaintTick() - entry\r\n");
	if(stBuilderAcquaintManger.m_eStatus != BUILDER_ACQUAINT_STATUS_IDLE && stBuilderAcquaintManger.m_u32TimeOut > 0)
	{
		s32Ret = 0;
		stBuilderAcquaintManger.m_u32TimeOut--;
		if(stBuilderAcquaintManger.m_u32TimeOut == 0)
		{
			mwDebug("BuilderAcquaintTick() - time out\r\n");
			if(stBuilderAcquaintManger.m_eStatus == BUILDER_ACQUAINT_STATUS_WAIT_LOCK)
			{
				mwError("BuilderAcquaintTick() - lock Freq %d time out\r\n", stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex].m_u32Freq);
			}
			else if(stBuilderAcquaintManger.m_eStatus == BUILDER_ACQUAINT_STATUS_DATA_RECEIVING)
			{
				mwDebug("BuilderAcquaintTick() - lock Freq %d OK but recv NIT time out\r\n", stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex].m_u32Freq);
				DvbBuilderReleaseFilter(stBuilderAcquaintManger.m_u32FilterID);
				stBuilderAcquaintManger.m_u32FilterID = BUILDER_INVALID_FILTER;
			}
			
			stBuilderAcquaintManger.m_u32CurIndex++;
			if(stBuilderAcquaintManger.m_u32CurIndex < stBuilderAcquaintManger.m_u32Num)
			{
				stBuilderAcquaintManger.m_u32TimeOut = 10;
				s32Ret = DvbBuilderTunerLock(&stBuilderAcquaintManger.m_pstTunerList[stBuilderAcquaintManger.m_u32CurIndex]);
				stBuilderAcquaintManger.m_eStatus = BUILDER_ACQUAINT_STATUS_WAIT_LOCK;
			}
		}
	}
	mwDebug("BuilderAcquaintTick() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int BuilderAcquaintGetSearchData(builder_ts_t* pstTs, builder_service_t* pstServices, unsigned int* pu32ServiceCnt, builder_section_t** ppstBat, builder_section_t** ppstNit)
{
	int s32Ret = -1;

	mwDebug("BuilderAcquaintGetSearchData() - entry, pstTs = %p, pstServices = %p, pu32ServiceCnt = %p, ppstBat = %p, ppstNit = %p\r\n", pstTs, pstServices, pu32ServiceCnt, ppstBat, ppstNit);
	if(stBuilderAcquaintManger.m_u32OperatorFound == 1)
	{
		*ppstNit = stBuilderAcquaintManger.m_pstNitSections;
		stBuilderAcquaintManger.m_pstNitSections = NULL;
		stBuilderAcquaintManger.m_u32OperatorFound = 0;
		s32Ret = 0;
	}
	mwDebug("BuilderAcquaintGetSearchData() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}


